package com.kgc.sbt.service.impl;

import com.kgc.sbt.constant.WxpayConstant;
import com.kgc.sbt.service.WxpayService;
import com.kgc.sbt.utils.HttpClient4Util;
import com.kgc.sbt.utils.WxpayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.TreeMap;

/**
 * Created on 2021/8/10.
 * <p>
 * Author: wuqilong
 * <p>
 * Description:
 */
@Service
@Slf4j
public class WxpayServiceImpl implements WxpayService {

    @Value("${wechat.pay.appId}")
    private String appId;

    @Value("${wechat.pay.mchId}")
    private String mchId;

    @Value("${wechat.pay.mchKey}")
    private String mchKey;

    @Value("${wechat.pay.orderUrl}")
    private String orderUrl;

    @Value("${wechat.pay.notifyUrl}")
    private String notifyUrl;

    @Override
    public String getWxpayOrderParamsXml(String body, int totalFee, String fromIp, String orderNum) throws Exception {

        //微信统一下单接口，要求参数按照参数名的字典序排列，使用treemap
        Map<String, String> paramsMap = new TreeMap<>();

        // 公众账号ID
        paramsMap.put("appid", appId);

        // 商户号
        paramsMap.put("mch_id", mchId);

        // 设备号 PC网页或公众号内支付可以传"WEB"
        paramsMap.put("device_info", "WEB");

        // 随机字符串
        paramsMap.put("nonce_str", WxpayUtil.generateNonceStrUseRandom());

        // 商品描述
        paramsMap.put("body", body);

        // 商户订单号
        paramsMap.put("out_trade_no", orderNum);

        // 标价金额
        paramsMap.put("total_fee", String.valueOf(totalFee));

        // 终端IP
        paramsMap.put("spbill_create_ip", fromIp);

        // 通知地址
        paramsMap.put("notify_url", notifyUrl);

        // 交易类型
        paramsMap.put("trade_type", WxpayConstant.WEPAY_ORDER_NATIVE);

        // 商品ID(trade_type=NATIVE时，此参数必传--实际应该是对应商品的id值)
        paramsMap.put("product_id", WxpayUtil.generateNonceStrUseUUID(9));

        // 签名处理，签名一般都是在最后进行，必须使用到上面所有的参数
        // 注意：sign参数是不参与签名逻辑，但是它是接口参数，必须将此参数传给微信官方
        // 微信官方根据上述参数重新签名跟当前sign参数值对比，确定请求是否可信
        paramsMap.put("sign", WxpayUtil.generateSignature(paramsMap, mchKey));

        // 将map参数转换为xml字符串格式返回
        return WxpayUtil.mapToXml(paramsMap);
    }

    @Override
    public Map<String, String> sendToWxpayUnifiedOrder(String wxpayOrderXml) throws Exception {
        // 发送请求到微信官方，统一下单，微信官方要求使用post，返回的内容是xml字符串
        String wxpayOrderReturnXml = HttpClient4Util.getResponse4PostByString(orderUrl,
                wxpayOrderXml, WxpayConstant.WXPAY_EDCODING_UTF8);

        // 解析返回xml字符串为map集合，返回
        return WxpayUtil.xmlToMap(wxpayOrderReturnXml);
    }

    @Override
    public String resolveWxpayResultNotify(String resultNotifyXml) throws Exception {
        // 将微信官方回调的字符串转为map集合
        Map<String, String> resultNotifyMap = WxpayUtil.xmlToMap(resultNotifyXml);

        // 只需要处理回调成功结果
        if(WxpayConstant.WXPAY_RETURN_CODE_SUCCESS.equals(resultNotifyMap.get("return_code"))){
            log.info("------ 3-1 微信官方异步通知支付结果：支付成功 ------");

            // 必须要做签名校验（金额校验等）
            if(WxpayUtil.isSignatureValid(resultNotifyMap, mchKey)){
                log.info("------ 3-2 微信官方异步通知签名校验：校验成功 ------");

                // TODO 进行对应的业务逻辑处理，比如修改订单支付状态
                return WxpayConstant.WXPAY_RESPONSE_RESULT_SUCCESS;
            }

            // 签名校验失败
            log.info("------ 3-2 微信官方异步通知签名校验：校验失败 ------");
        }

        return WxpayConstant.WXPAY_RESPONSE_RESULT_FAIL;
    }
}
